<?php

/**
 * 数据库 - 模型类
 * 
 * @package    01CMS
 * @subpackage system
 * @author     rolong at vip.qq.com
 * @version    1.0.0
 * @link       http://www.01cms.com
 */

class DbModel extends Base
{
    public $debug = FALSE;
    public $prefix;
    public $insertId = 0;
    public $table;
    public $linkId;
    
    protected $sql;
    protected $result = array();
    protected $primaryKey = 'id';

    function __construct ()
    {
        $parentName = get_class($this);
        
        $Base = Base::i();
        
        foreach (array_keys(get_object_vars($Base)) as $key)
        {
            if ((! isset($this->$key) || $this->$key == 'table') && $key != $parentName)
            {
                $this->$key = NULL;
                $this->$key = & $Base->$key;
            }
        }
        
        if (empty($this->table))
        {
            $c = strtolower($this->c);
            $this->table = "@@__{$c}_{$this->m}";
        }
        
        $this->connect($this->Load->config['mysql']);
    }

    /**
     * 连接数据库
     * 
     * @param array $config
     * @return void
     * @access 	public
     */
    function connect ($config)
    {
        $this->prefix = $config['prefix'];
        
        if ($config['pconnect'])
        {
            $this->linkId = mysql_pconnect($config['hostname'], $config['username'], $config['password']);
        }
        else
        {
            $this->linkId = mysql_connect($config['hostname'], $config['username'], $config['password']);
        }
        
        if (! $this->linkId)
        {
            showError("No MySql connection!");
        }
        
        mysql_select_db($config['database']);
        
        mysql_query("SET NAMES '{$config['charset']}', character_set_client=binary, sql_mode='' ;", $this->linkId);
    }

    /**
     * 运行SQL语句
     * 
     * @param string $sql
     * @param mix $id
     * @return bool
     * @access 	public
     */
    function query ($sql = '', $id = 0)
    {
        if ($sql != '')
        {
            $this->setSql($sql);
        }
        
        if ($this->sql == '')
        {
            showError('The sql string is empty!');
        }
        
        if ($this->debug)
        {
            $Test = lib('Test');
            
            $Test->init();
            
            $Test->startTime();
            
            $this->result[$id] = mysql_query($this->sql, $this->linkId);
            
            $Test->stopTime();
            
            echo "<br />---------------{$Test->spentTime()}---------------<br />{$this->sql}<br />";
        }
        else
        {
            $this->result[$id] = mysql_query($this->sql, $this->linkId);
        }
        
        if ($this->result[$id] === false)
        {
            showError(mysql_error() . " <br /><br />Error sql: " . $this->sql);
        }
        
        return true;
    }

    /**
     * 获取运行SQL语句后影响的行数
     * 
     * @return int
     * @access 	public
     */
    function getAffectedRows ()
    {
        return mysql_affected_rows();
    }

    /**
     * 获取MySQL错误
     * 
     * @return int
     * @access 	public
     */
    function getError ()
    {
        return mysql_error();
    }

    /**
     * 设置SQL语句前缀
     * 
     * @param string $sql
     * @return int
     * @access 	public
     */
    function setSql ($sql)
    {
        $this->sql = str_replace("@@__", $this->prefix, $sql);
    }

    /**
     * 取出一条记录中第一列的值
     * 
     * @param string $sql
     * @return string
     * @access public
     */
    function getOne ($sql)
    {
        $this->query($sql, 'one');
        $row = mysql_fetch_array($this->result['one'], MYSQL_NUM);
        return isset($row['0']) ? $row['0'] : FALSE;
    }

    /**
     * 取出一条记录，如果参数$sql为一个数字，读取id等于这个参数值的记录
     * 
     * @param string $sql
     * @param mix $id
     * @param string $type [array|object]
     * @return array (返回一维数组)
     * @access public
     */
    function getRow ($sql, $id = 0, $type = '', $resultType = MYSQL_ASSOC)
    {
        if (is_numeric($sql))
        {
            $sql = "SELECT * FROM {$this->table} WHERE {$this->primaryKey} = {$sql} LIMIT 1";
        }
        
        if (! eregi('limit', $sql))
        {
            $this->setSql(eregi_replace("[,;]$", '', trim($sql)) . " limit 1;");
        }
        else
        {
            $this->setSql($sql);
        }
        
        $this->query('', $id);
        
        $row = $this->getNextRow($id, $type, $resultType);
        
        if (empty($row))
        {
            return array();
        }
        else
        {
            mysql_free_result($this->result[$id]);
            
            return $row;
        }
    }

    /**
     * 取出多条记录
     * 
     * @param string $sql
     * @param mix $id
     * @param string $type (array|object)
     * @return array (返回二维数组)
     * @access public
     */
    function getRows ($sql, $id = 0, $type = '', $resultType = MYSQL_ASSOC)
    {
        $this->setSql($sql);
        
        $this->query('', $id);
        
        while ($row = $this->getNextRow($id, $type, $resultType))
        {
            $rows[] = $row;
        }
        
        if (! isset($rows))
        {
            return array();
        }
        
        mysql_free_result($this->result[$id]);
        
        return $rows;
    }

    /**
     * 取出下一条记录
     * 
     * @param mix $id
     * @param string $type (array|object)
     * @return array (返回一维数组)
     * @access public
     */
    function getNextRow ($id = 0, $type = '', $resultType = MYSQL_ASSOC)
    {
        if (! isset($this->result[$id]))
        {
            return false;
        }
        else
        {
            if (strtolower($type) == 'array')
            {
                $data = mysql_fetch_array($this->result[$id], $resultType);
                
                if (! empty($data))
                {
                    foreach ($data as $key => $value)
                    {
                        if (strpos($value, '\\') !== FALSE)
                        {
                            $data["{$key}"] = stripslashes($value);
                        }
                    }
                }
                
                return $data;
            }
            else
            {
                $data = mysql_fetch_object($this->result[$id]);
                
                if (! empty($data))
                {
                    foreach ($data as $key => $value)
                    {
                        if (strpos($value, '\\') !== FALSE)
                        {
                            $data->{$key} = stripslashes($value);
                        }
                    }
                }
                
                return $data;
            }
        }
    }

    /**
     * 插入记录
     * 
     * @param array $data
     * @param string $table
     * @return Insert id or false
     * @access public
     */
    function insert ($data, $table = '')
    {
        if ($table == '')
        {
            $table = $this->table;
        }
        
        $values = '';
        
        $fields = '';
        
        $fieldInsertedCount = 0;
        
        foreach ($data as $name => $value)
        {
            $fields .= "`" . $name . "`, ";
            
            $value = mysql_real_escape_string($value);
            
            $values .= "'" . $value . "', ";
            
            $fieldInsertedCount ++;
        }
        
        if ($fieldInsertedCount <= 0)
        {
            return false;
        }
        
        $fields = substr($fields, 0, - 2);
        
        $values = substr($values, 0, - 2);
        
        $status = $this->query('insert into ' . $table . ' (' . $fields . ') values (' . ($values) . ')');
        
        if ($status)
        {
            return mysql_insert_id();
        }
        
        return FALSE;
    }

    /**
     * 更新记录
     * 
     * @param array $data
     * @param string $where
     * @param string $table
     * @return bool
     * @access public
     */
    function update ($data, $where, $table = '')
    {
        if (is_numeric($where))
        {
            $where = $this->primaryKey . '=' . $where;
        }
        
        if ($table == '')
        {
            $table = $this->table;
        }
        
        $str = '';
        
        $count = 0;
        
        foreach ($data as $name => $value)
        {
            $value = mysql_real_escape_string($value);
            
            $str .= "`{$name}` = '{$value}', ";
            
            $count ++;
        }
        
        if ($count <= 0)
        {
            return false;
        }
        
        $str = substr($str, 0, - 2);
        
        return $this->query("update {$table} set {$str} where {$where}");
    }

    function del ($where, $table = '')
    {
        return $this->delete($where, $table);
    }

    /**
     * 删除记录
     * 
     * @param string $where
     * @param string $table
     * @return bool
     * @access public
     */
    function delete ($where, $table = '')
    {
        if (is_numeric($where))
        {
            $where = $this->primaryKey . '=' . $where;
        }
        
        if ($table == '')
        {
            $table = $this->table;
        }
        
        return $this->query("DELETE FROM {$table} WHERE {$where}");
    }

    /**
     * 数据分页列表
     * 
     * @return 	array
     * @access 	public
     */
    function lists ()
    {
        $Base = Base::i();
        
        if (! empty($Base->table))
        {
            $this->table = $Base->table;
        }
        
        if (empty($this->where))
        {
            $this->where = empty($Base->where) ? '' : 'WHERE ' . $Base->where;
        }
        else
        {
            $this->where = 'WHERE ' . $this->where;
        }
        
        if (empty($this->mainSql))
        {
            $this->mainSql = empty($Base->mainSql) ? "SELECT * FROM `{$this->table}`" : $Base->mainSql;
        }
        
        if (empty($this->countSql))
        {
            $this->countSql = empty($Base->mainSql) ? "SELECT count(*) as num FROM `{$this->table}` {$this->where}" : $Base->mainSql;
        }
        
        if (empty($this->order))
        {
            $this->order = empty($Base->order) ? '' : 'ORDER BY ' . $Base->order;
        }
        else
        {
            $this->order = 'ORDER BY ' . $this->order;
        }
        
        if (empty($this->pageParam))
        {
            $this->pageParam = empty($Base->pageParam) ? 1 : $Base->pageParam;
        }
        
        if (empty($this->pageSize))
        {
            $this->pageSize = empty($Base->pageSize) ? 20 : $Base->pageSize;
        }
        
        if (empty($this->start))
        {
            if (isset($Base->start))
            {
                $this->start = $Base->start;
            }
            else
            {
                $this->start = isset($this->p[$this->pageParam]) ? $this->p[$this->pageParam] : 0;
            }
        }
        
        $this->start = ($this->start > 0) ? intval($this->start) : 0;
        
        if (empty($this->baseUrl))
        {
            $this->baseUrl = empty($Base->baseUrl) ? '' : $Base->baseUrl;
        }
        
        $count = $this->getRow($this->countSql);
        
        lib('Pagination')->createLinks(array('pageParam'=>$this->pageParam, 'baseUrl'=>$this->baseUrl, 'totalRows'=>$count->num, 'pageSize'=>$this->pageSize));
        
        return $this->getRows("{$this->mainSql} {$this->where} {$this->order} LIMIT {$this->start}, {$this->pageSize}");
    }

    /**
     * 更新排序
     * 
     * @param 	string $ids 用逗号隔开,如:1,2,3
     * @param   string $table
     * @return 	void
     * @access 	public
     */
    function ordering ($ids, $table = '')
    {
        if (empty($table))
        {
            $table = $this->table;
        }
        
        $i = 0;
        $ids = explode(',', $ids);
        
        foreach ($ids as $id)
        {
            $status = $this->update(array('ordering'=>$i), "id = {$id}", $table);
            
            if (! $status)
            {
                return FALSE;
            }
            
            $i ++;
        }
        
        return TRUE;
    }
}

// END